import 'isomorphic-fetch';
import { stringify } from 'querystring';

const parse = res => {
  if (res.ok) {
    if (res.status === 204 || res.status === 201) {
      return { ...res };
    }
    return res.json().then(result => {
      if (Array.isArray(result)) {
        return result;
      }
      return { ...res, ...result };
    });
  }
  return new Promise((resolve, reject) => {
    try {
      res.json().then(error => {
        reject(error);
      });
    } catch ({ status, statusText }) {
      reject(`${status} ${statusText}`);
    }
  });
};

export default function xFetch(url, options = {}) {

  const opts = {
    ...options,
    credentials: 'same-origin',
    headers: {
      Accept: 'application/json',
      'Content-Type': 'application/json',
      ...options.headers
    }
  };

  return fetch(url, opts)
    .then(res => parse(res, url, opts));
}

export async function get(url, parameters, options) {
  const paramStr = stringify(parameters);
  const realPath = paramStr ? `${url}?${stringify(parameters)}` : url;
  return xFetch(realPath, options);
}

export function forward(url, parameters) {
  const paramStr = stringify(parameters);
  const realPath = paramStr ? `${url}?${stringify(parameters)}` : url;
  window.location.href = realPath;
}

export async function post(url, parameters, options) {
  return xFetch(url, {
    method: 'POST',
    body: JSON.stringify(parameters),
    ...options
  });
}

export async function put(url, parameters, options) {
  return xFetch(url, {
    method: 'PUT',
    body: JSON.stringify(parameters),
    ...options
  });
}

export async function patch(url, parameters, options) {
  return xFetch(url, {
    method: 'PATCH',
    body: JSON.stringify(parameters),
    ...options
  });
}

export async function del(url, parameters, options) {
  const paramStr = stringify(parameters);
  const realPath = paramStr ? `${url}?${stringify(parameters)}` : url;
  return xFetch(realPath, {
    method: 'DELETE',
    ...options
  });
}
